#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_system.h"
#include "esp_spi_flash.h"

#include "esp_err.h"

#include "driver/gpio.h"
// #include "ldg_i2c.h"
#include "GXHTC3.h"
#include "QMI8658C.h"
#include "QMC5883L.h"

static const char *TAG = "ITLDG";

static QueueHandle_t gpio_evt_queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void *arg)
{
  uint32_t gpio_num = (uint32_t)arg;
  xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}

static void gpio_task_example(void *arg)
{
  uint32_t io_num;
  for (;;)
  {
    if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY))
    {
      printf("GPIO[%" PRIu32 "] intr, val: %d\n", io_num, gpio_get_level(io_num));
    }
  }
}

// static void gxhtc3_task(void *args)
// {
//   esp_err_t ret;

//   while (1)
//   {
//     ret = gxhtc3_get_tah();
//     if (ret != ESP_OK)
//     {
//       ESP_LOGE(TAG, "获取温湿度出错.");
//     }
//     else
//     {
//       ESP_LOGI(TAG, "TEMP:%.1f HUMI:%.1f", temp, humi);
//       ESP_LOGI(TAG, "TEMP:%d HUMI:%d", temp_int, humi_int);
//     }
//     vTaskDelay(1000 / portTICK_PERIOD_MS);
//   }
// }

void app_main()
{
  gpio_config_t io_conf = {
      .intr_type = GPIO_INTR_NEGEDGE,  // falling edge interrupt
      .mode = GPIO_MODE_INPUT,         // set as input mode
      .pin_bit_mask = 1 << GPIO_NUM_9, // bit mask of the pins GPIO9
      .pull_down_en = 0,               // disable pull-down mode
      .pull_up_en = 1                  // enable pull-up mode
  };
  // configure GPIO with the given settings
  gpio_config(&io_conf);

  // create a queue to handle gpio event from isr
  gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
  // start gpio task
  xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);

  // install gpio isr service
  gpio_install_isr_service(0);
  // hook isr handler for specific gpio pin
  gpio_isr_handler_add(GPIO_NUM_9, gpio_isr_handler, (void *)GPIO_NUM_9);

  printf("Hello world!\n");

  /* Print chip information */
  esp_chip_info_t chip_info;
  esp_chip_info(&chip_info);
  printf("This is ESP32 chip with %d CPU cores, WiFi%s%s, ",
         chip_info.cores,
         (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
         (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

  printf("silicon revision %d, ", chip_info.revision);

  printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
         (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

  // for (int i = 10; i >= 0; i--)
  // {
  //   printf("Restarting in %d seconds...\n", i);
  //   vTaskDelay(1000 / portTICK_PERIOD_MS);
  // }
  // printf("Restarting now.\n");
  // fflush(stdout);
  // esp_restart();

  // gxhtc3_task
  // xTaskCreate(gxhtc3_task, "gxhtc3_task", 4096, NULL, 6, NULL);

  ldg_i2c_master_init();

  // qmi8658c_init();

  // t_sQMI8658C QMI8658C;
  // while (1)
  // {
  //   vTaskDelay(1000 / portTICK_PERIOD_MS);
  //   qmi8658c_fetch_angleFromAcc(&QMI8658C);
  //   ESP_LOGI(TAG, "angle_x = %.1f  angle_y = %.1f angle_y = %.1f", QMI8658C.AngleX, QMI8658C.AngleY, QMI8658C.AngleZ);
  // }

  qmc5883l_init();
  t_sQMC5883L QMC5883L;
  while (1)
  {
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    qmc5883l_fetch_azimuth(&QMC5883L);
    ESP_LOGI(TAG, "azimuth = %.1f", QMC5883L.azimuth);
  }
}